package com.easepal.softaplib;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.util.Arrays;

/**
 * 作者: bright.lin@medisana.net.cn
 * 时间: 2018/12/19
 * 标题: BIO的Socket客户端
 * 描述: 用于与设备热点建立TCP连接的Socket客户端
 * 修改: 由 bright.lin@medisana.net.cn 修改于 2018/12/19
 */
@SuppressWarnings("unused")
public class BioClient {

    // Socket连接管理对象
    private BioConnector mConnector;
    // 发送消息
    private String sendMsg;
    // 连接监听回调
    private IConnectListener mIConnectListener;
    // 输出流
    private OutputStream mOutputStream = null;
    // 输入流
    private InputStream mInputStream = null;

    /**
     * 带参构造器
     *
     * @param mConnectListener 连接监听回调
     */
    public BioClient(IConnectListener mConnectListener) {
        this.mIConnectListener = mConnectListener;
        mConnector = new BioConnector(this, mConnectListener);
    }

    /**
     * 设置连接地址
     *
     * @param ip   ip地址
     * @param port 端口
     */
    public void setConnectAddress(String ip, int port) {
        mConnector.setConnectAddress(ip, port);
    }

    /**
     * 设置连接超时
     *
     * @param connectTimeout 超时时长
     */
    public void setConnectTimeout(long connectTimeout) {
        mConnector.setConnectTimeout(connectTimeout);
    }

    /**
     * 连接
     */
    public void connect() {
        mConnector.connect();
    }

    /**
     * 断开连接
     */
    public void disconnect() {
        mConnector.disconnect();
    }

    /**
     * 重连
     */
    public void reconnect() {
        mConnector.reconnect();
    }

    /**
     * 发送消息
     *
     * @param msg 消息
     */
    public void sendMsg(String msg) {
        sendMsg = msg;
        mConnector.checkConnect();
    }

    /**
     * 获取已连接状态
     *
     * @return 是否已连接
     */
    public boolean isConnected() {
        return mConnector.isConnected();
    }

    /**
     * 初始化输入输出流
     *
     * @param mOutputStream 输出流
     * @param mInputStream  输入流
     */
    void init(OutputStream mOutputStream, InputStream mInputStream) {
        this.mOutputStream = mOutputStream;
        this.mInputStream = mInputStream;
    }

    /**
     * 关闭输入输出流
     */
    void onClose() {
        mOutputStream = null;
        mInputStream = null;
    }

    /**
     * 从输入流读取信息
     */
    void onRead() {
        try {
            int maximum_length = 64 * 1024;
            byte[] bodyBytes = new byte[maximum_length];
            int numRead;

            while ((numRead = mInputStream.read(bodyBytes, 0, maximum_length)) > 0) {
                byte[] readBytes = Arrays.copyOfRange(bodyBytes, 0, numRead);
                if (null != mIConnectListener) {
                    mIConnectListener.onMessage(readBytes);
                }
            }
        } catch (SocketException e) {
            // 客户端主动socket.stopConnect()会调用这里 java.net.SocketException: Socket closed
            e.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (Exception e2) {
            e2.printStackTrace();
        }
    }

    /**
     * 写入信息至输出流
     * @return 是否写入成功
     */
    boolean onWrite() {
        boolean writeRet;
        try {
            if (null != sendMsg) {
                mOutputStream.write(sendMsg.getBytes());
                mOutputStream.flush();
            }
            writeRet = true;
        } catch (SocketException e) {
            e.printStackTrace();//客户端主动socket.stopConnect()会调用这里 java.net.SocketException: Socket closed
            writeRet = false;
        } catch (IOException e1) {
            e1.printStackTrace();//发送的时候出现异常，说明socket被关闭了(服务器关闭)java.net.SocketException: sendto failed: EPIPE (Broken pipe)
            writeRet = false;
        } catch (Exception e2) {
            e2.printStackTrace();
            writeRet = false;
        }

        return writeRet;
    }
}
